package com.fanh.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fanh.common.exception.Asserts;
import com.fanh.common.util.CommonUtil;
import com.fanh.common.util.PayTypeEnum;
import com.fanh.common.wxpay.sdk.WXPay;
import com.fanh.common.wxpay.sdk.WXPayUtil;
import com.fanh.conf.MyConfig;
import com.fanh.mapper.GuideCoinHistoryMapper;
import com.fanh.mapper.GuideCoinMapper;
import com.fanh.mapper.GuideCoinOrderMapper;
import com.fanh.mapper.SysUserMapper;
import com.fanh.model.*;
import com.fanh.service.GuideCoinOrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.*;

@Service("guideCoinOrderService")
public class GuideCoinOrderServiceImpl  implements GuideCoinOrderService {

    private Logger LOGGER = LoggerFactory.getLogger(GuideCoinOrderServiceImpl.class);

    @Value("${wx.notifyUrl}")
    private String notifyUrl;
    @Value("${wx.certUrl}")
    private  String certPath;
    @Value("${wx.appid}")
    private String appID;
    @Value("${wx.mchid}")
    private String mchID;
    @Value("${wx.apikey}")
    private String key;
     @Value("${apple.certificateUrl}")
    private String certificateUrl;
    @Value("${apple.certificateUrlTest}")
    private String certificateUrlTest;





    @Autowired
    private GuideCoinOrderMapper guideCoinOrderMapper;
    @Autowired
     private SysUserMapper sysUserMapper;
    @Autowired
    private GuideCoinMapper guideCoinMapper;
    @Autowired
    private GuideCoinHistoryMapper guideCoinHistoryMapper;

    @Override
    public GuideCoinOrder insert(GuideCoinOrder order) {
         SysUser user = sysUserMapper.selectByPrimaryKey(order.getUserId());
         if(user == null) {
             Asserts.fail("用户登录异常，下单失败");
         }
         order.setUserName(user.getName());
        int i = guideCoinOrderMapper.insert(order);
        if(i<1){
            Asserts.fail("系统异常，下单失败");
        }
        return order;
    }

    @Override
    public GuideCoinOrder update(GuideCoinOrderExample order) {
        return null;
    }

    @Override
    public Map<String, String> wxPay(Long orderId, HttpServletRequest request) throws Exception {


        MyConfig config = new MyConfig(certPath,appID,mchID,key);
        GuideCoinOrder order  = guideCoinOrderMapper.selectByPrimaryKey(orderId);

        if(order == null ){
            Asserts.fail("操作失败，订单不存在");
        }

        WXPay wxpay = new WXPay(config, notifyUrl);

        Map<String, String> data = new HashMap<String, String>();
        data.put("body", "指点订单充值");
        data.put("out_trade_no", order.getOrderSn());
        data.put("fee_type", "CNY");
        data.put("total_fee",order.getPayAmount().multiply(new BigDecimal(100)).intValue()+"");
        data.put("spbill_create_ip", CommonUtil.getClientIp(request));
        data.put("notify_url", notifyUrl);
        data.put("trade_type", "APP");
        //data.put("openid", "oC1vd5T9FuyS4Bpa9KOP2UGh0T-I");
       // data.put("openid", member.getWxOpenId());
        Map<String, String> resp = wxpay.unifiedOrder(data);

        Map<String, String> map = new HashMap<String, String>();

        String return_code = resp.get("return_code");//返回状态码
        String result_code = resp.get("result_code");//结果状态码
        String nonce_str = resp.get("nonce_str"); //随即字符串

        Long s = System.currentTimeMillis() / 1000;//获取时间戳除以千变字符串

        String timeStamp = String.valueOf(s);
        if ("SUCCESS".equals(return_code) && return_code.equals(result_code)) {
            map.put("appid", config.getAppID());//你的appid
            map.put("partnerid", config.getMchID());
            map.put("prepayid", resp.get("prepay_id"));
            map.put("package", "Sign=WXPay");
            map.put("noncestr", nonce_str);
            map.put("timestamp", timeStamp);
            map.put("sign", "MD5");
             System.out.println("二次签名参数 ： " + map);//需要生成二次签名 所用的参数
            //再次签名sign，这个签名用于小程序端调用wx.requesetPayment方法
            String sign = WXPayUtil.generateSignature(map, config.getKey());//你的商户号key
            map.put("sign", sign); // 生成签名 重要
            System.out.println("生成的签名paySign : " + sign);
        }
        return map;
    }

    @Override
    public String payBack(HttpServletRequest request)  {

        try {
            //读取参数
            InputStream inputStream;
            StringBuffer sb = new StringBuffer();
            inputStream = request.getInputStream();
            String s;
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            while ((s = in.readLine()) != null){
                sb.append(s);
            }
            in.close();
            inputStream.close();

            //解析xml成map
            Map<String, String> m = WXPayUtil.xmlToMap(sb.toString());
            //过滤空 设置 TreeMap
            Iterator it = m.keySet().iterator();
            while (it.hasNext()) {
                String parameter = (String) it.next();
                String parameterValue = m.get(parameter);

                if(null != parameterValue) {

                    m.put(parameter,parameterValue.trim());
                }else{
                    m.remove(parameter);
                }
            }
            if(WXPayUtil.isSignatureValid(m, key)) {
                if(!"SUCCESS".equals((String)m.get("result_code"))){
                    //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                    Asserts.fail("支付失败,错误信息：" + m.get("err_code"));
                }
            }else{
                Asserts.fail("通知签名验证失败");
            }
            return paySuccess(m.get("out_trade_no"), PayTypeEnum.WxPay,m.get("out_trade_no"));
        } catch (Exception e) {
            e.printStackTrace();
             return CommonUtil.setXML("FAIL","FIAl");
        }


    }

    @Override
    public int applePay(String orderSn, String certificateCode)  {
         try {
            String sendHttpsCoon = CommonUtil.sendHttpsCoon(certificateUrl, certificateCode);
            JSONObject json = JSONObject.parseObject(sendHttpsCoon);
            if ("21007".equals(json.get("status").toString())) {
                 sendHttpsCoon = CommonUtil.sendHttpsCoon(certificateUrlTest, certificateCode);  //发送请求
            }
            JSONObject jsonObject = JSONObject.parseObject(sendHttpsCoon);
            if ("0".equals(jsonObject.get("status").toString())) {	//苹果服务器向返回status结果
                JSONArray inapp = (JSONArray) ((JSONObject) jsonObject.get("receipt")).get("in_app");
                if (inapp.size() > 0) { //如果订单状态成功在判断in_app这个字段有没有，没有直接就返回失败了。如果存在的话，遍历整个数组，通过客户端给的transaction_id 来比较
                    JSONObject parseObject = (JSONObject) inapp.get(0);
                    String product_id = parseObject.get("product_id").toString();
                    String transaction_id = parseObject.get("transaction_id").toString();
                    paySuccess(orderSn,PayTypeEnum.ApplePay,transaction_id);

                    return  1;
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     *
     * @param orderSn
     * @param payType 1->支付宝；2->微信; 3->苹果支付
     * @return
     * @throws Exception
     */
    public String paySuccess(String  orderSn,Integer payType,String transaction_id)  {
        //拿到订单号
        GuideCoinOrderExample example =new GuideCoinOrderExample();
        example.createCriteria().andOrderSnEqualTo(orderSn);
        GuideCoinOrder order =guideCoinOrderMapper.selectByExample(example).get(0);
        order.setPayType(payType);
        order.setPaymentTime(new Date());
        order.setStatus(1);
        order.setTransactionId(transaction_id);
        //修改订单状态
       int count = guideCoinOrderMapper.updateByPrimaryKeySelective(order);
        //将个人余额里面增加虚拟币
        GuideCoinExample coinExample = new GuideCoinExample();
        coinExample.createCriteria().andUserIdEqualTo(order.getUserId());
        GuideCoin coin = guideCoinMapper.selectByExample(coinExample).get(0);

        coin.setBalance(coin.getBalance().add(order.getIcoinAmount()).add(order.getSendIcoinAmount()));
        count=count+guideCoinMapper.updateByPrimaryKey(coin);

        //增加虚拟币 记录表
        GuideCoinHistory history = new GuideCoinHistory();
        history.setAccount(coin.getId());
        history.setUserId(order.getUserId());
        history.setCoin(order.getIcoinAmount().add(order.getSendIcoinAmount()));
        history.setCreateDate(new Date());
        history.setPrice(order.getPayAmount());
        history.setType(0);
        history.setNote("订单充值orderSn:"+orderSn+";并赠送虚拟币："+order.getSendIcoinAmount());
        count=count+ guideCoinHistoryMapper.insertSelective(history);
        if(count<3){
            Asserts.fail("支付回调失败");
        }

         return  CommonUtil.setXML("SUCCESS","OK");
    }

}
